/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.cdp.cdf.component.metadata.serializer.obsolete.commonCmp;

import com.fasterxml.jackson.databind.JsonNode;
import com.inspur.edp.caf.cef.schema.base.datatype.impl.DefaultCollectionType;
import com.inspur.edp.caf.cef.schema.base.datatype.impl.DefaultMapType;
import com.inspur.edp.caf.cef.schema.base.datatype.impl.DefaultPrimitiveType;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.DataTypeDeSerializer;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.DataTypeSerializer;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.impl.DefaultCollectionTypeSerializer;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.impl.DefaultMapTypeSerializer;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.impl.DefaultPrimitiveTypeSerializer;
import com.inspur.edp.caf.cef.schema.base.datatype.serializer.impl.ObjectTypeSerializer;
import com.inspur.edp.caf.cef.schema.base.serializer.DataTypeSerializerFactory;
import com.inspur.edp.caf.cef.schema.base.serializer.SerializeContext;
import com.inspur.edp.caf.cef.schema.base.utils.JsonUtil;
import com.inspur.edp.caf.cef.schema.datatype.DataType;
import com.inspur.edp.caf.cef.schema.datatype.ObjectType;
import com.inspur.edp.cdp.cdf.component.manager.exception.CompExceptionCode;
import com.inspur.edp.cdp.cdf.component.manager.exception.CompSerializationException;
import com.inspur.edp.cdp.cdf.component.manager.exception.UnSupportedDataTypeException;
import com.inspur.edp.cdp.cdf.component.manager.serializer.ArrayTypeSerializer;
import com.inspur.edp.cdp.cdf.component.manager.serializer.CompParamTypeSerializer;
import com.inspur.edp.cdp.cdf.component.manager.serializer.CustomTypeSerializer;
import com.inspur.edp.cdp.cdf.component.manager.serializer.DefaultCompSerializerContext;
import com.inspur.edp.cdp.cdf.component.manager.serializer.StructureTypeReferSerializer;
import com.inspur.edp.component.schema.GspCompParamType;
import com.inspur.edp.component.schema.StructuredTypeRefer;
import com.inspur.edp.component.schema.type.array.ArrayType;
import com.inspur.edp.component.schema.type.custom.CustomType;
import com.inspur.edp.component.schema.utils.DataTypeConverter;

/**
 * @author Kaixuan Shi
 * @version 0.1
 */
public class CommonCompParamTypeSerializer extends CompParamTypeSerializer {

    @Override
    public JsonNode serialize(DataType dataType, SerializeContext serializeContext) {
        if (!(dataType instanceof GspCompParamType)) {
            throw new UnSupportedDataTypeException(dataType.getKind());
        }
        GspCompParamType paramType = (GspCompParamType) dataType;
        return this.serializeToDefaultDataType(paramType);

    }

    //序列化为单一DataType类型
    private JsonNode serializeToDefaultDataType(GspCompParamType paramType) {
        DataType defaultDataType = DataTypeConverter.getDefaultDataType(paramType);
        SerializeContext context = getDefaultDataTypeSerializeContext();
        DataTypeSerializer dataTypeSerializer = context.getDataTypeSerializerFactory().getSerializer(defaultDataType);
        return dataTypeSerializer.serialize(defaultDataType, context);
    }

    //endregion
    private void checkParamType(GspCompParamType paramType) {
        if (!paramType.isValid()) {
            throw new CompSerializationException(CompExceptionCode.GSP_COMPONENT_SERIALIZE_0006,
                    "Class \"GspCompParamType\" required fields are not assigned:" + JsonUtil.serialize(paramType), false);
        }

    }

    private static SerializeContext getDefaultDataTypeSerializeContext() {
        DefaultCompSerializerContext context = new DefaultCompSerializerContext();
        DataTypeSerializerFactory dataTypeSerializerFactory = new ParamTypeDataTypeFactory();
        context.setDataTypeSerializerFactory(dataTypeSerializerFactory);

        return context;
    }

    private static class ParamTypeDataTypeFactory implements DataTypeSerializerFactory {

        @Override
        public DataTypeSerializer getSerializer(DataType dataType) {
            if (dataType instanceof DefaultPrimitiveType) {

                return new DefaultPrimitiveTypeSerializer();
            } else if (dataType instanceof DefaultCollectionType) {

                return new DefaultCollectionTypeSerializer();
            } else if (dataType instanceof DefaultMapType) {

                return new DefaultMapTypeSerializer();
            } else if (dataType instanceof ArrayType) {

                return new ArrayTypeSerializer();
            } else if (dataType instanceof ObjectType) {

                return new ObjectTypeSerializer();
            } else if (dataType instanceof CustomType) {

                return new CustomTypeSerializer();
            } else if (dataType instanceof StructuredTypeRefer) {

                return new StructureTypeReferSerializer();
            } else {
                throw new UnSupportedDataTypeException(dataType.getKind());
            }
        }

        @Override
        public DataTypeDeSerializer getDeSerializer(String kind) {
            if (kind == null) {
                throw new UnSupportedDataTypeException("No \"kind\" field");
            }
            switch (kind) {
                case DefaultPrimitiveType.KIND:
                    return new DefaultPrimitiveTypeSerializer();
                case DefaultCollectionType.KIND:
                    return new DefaultCollectionTypeSerializer();
                case DefaultMapType.KIND:
                    return new DefaultMapTypeSerializer();
                case ArrayType.KIND:
                    return new ArrayTypeSerializer();
                case ObjectType.KIND:
                    return new ObjectTypeSerializer();
                case CustomType.KIND:
                    return new CustomTypeSerializer();
                case StructuredTypeRefer.KIND:
                    return new StructureTypeReferSerializer();
                default:
                    throw new UnSupportedDataTypeException(kind);
            }
        }
    }
}
